<template>
  <div class="custom-page">
    <template v-if="pageData.left">
      <transition
        appear
        name="animate__animated animate__bounce"
        enter-active-class="animate__slideInLeft"
      >
        <div class="left">
          <a-row class="modules-row" :gutter="[12, 0]">
            <draggable
              class="drag-list-left"
              group="dragList"
              v-model="pageData.left"
              v-bind="dragOptions"
              handle=".drag-icon"
              :move="onMoveLeft"
              @add="onLeftDragFinish"
              @update="onDragUpdate"
              item-key="id"
            >
              <template #item="{ element, index }">
                <a-col
                  :span="element.columns == 2 ? 24 : 12"
                  class="modules-col"
                  :style="{ height: element.rows == 2 ? '50%' : '25%' }"
                  v-if="element.id > 0"
                >
                  <EditItem
                    :data="element"
                    :side="'left'"
                    :index="index"
                    @onAdd="addModule"
                    @onDelete="onModuleDelete"
                  />
                </a-col>
                <a-col
                  :span="12"
                  class="modules-col"
                  style="height: 25%"
                  v-else
                >
                  <div class="empty-item-wrap">
                    <div
                      class="empty-item"
                      @click="
                        addModule('left', pageData.left.length - 1, 'add')
                      "
                    >
                      <PlusOutlined
                        style="font-size: 2.8rem; margin-bottom: 1rem"
                      />
                      <div>添加数据组件</div>
                    </div>
                  </div>
                </a-col>
              </template>
            </draggable>
          </a-row>
        </div>
      </transition>
    </template>
    <template v-if="pageData.right">
      <transition
        appear
        name="animate__animated animate__bounce"
        enter-active-class="animate__slideInRight"
      >
        <div class="right">
          <a-row class="modules-row" :gutter="[12, 0]">
            <draggable
              class="drag-list-right"
              group="dragList"
              v-model="pageData.right"
              v-bind="dragOptions"
              handle=".drag-icon"
              :move="onMoveRight"
              @add="onRightDragFinish"
              @update="onDragUpdate"
              item-key="id"
            >
              <template #item="{ element, index }">
                <a-col
                  :span="element.columns == 2 ? 24 : 12"
                  class="modules-col"
                  :style="{ height: element.rows == 2 ? '50%' : '25%' }"
                  v-if="element.id > 0"
                >
                  <EditItem
                    :data="element"
                    :side="'right'"
                    :index="index"
                    @onAdd="addModule"
                    @onDelete="onModuleDelete"
                  />
                </a-col>
                <a-col
                  :span="12"
                  class="modules-col"
                  style="height: 25%"
                  v-else
                >
                  <div class="empty-item-wrap">
                    <div
                      class="empty-item"
                      @click="
                        addModule('right', pageData.right.length - 1, 'add')
                      "
                    >
                      <PlusOutlined
                        style="font-size: 2.8rem; margin-bottom: 1rem"
                      />
                      <div>添加数据组件</div>
                    </div>
                  </div>
                </a-col>
              </template>
            </draggable>
          </a-row>
        </div>
      </transition>
    </template>

    <template v-if="pageData.left || pageData.right">
      <transition
        appear
        name="animate__animated animate__bounce"
        enter-active-class="animate__slideInUp"
      >
        <div class="save-button">
          <a-button
            type="primary"
            style="padding-left: 2rem; padding-right: 2rem"
            @click="onSubmit"
            :loading="submitLoading"
          >
            <template #icon>
              <SaveOutlined />
            </template>
            发布</a-button
          >
        </div>
      </transition>
    </template>

    <ChooseModule
      :visible="showAddModuleVisible"
      @onClose="onChooseModuleClose"
    />
  </div>
</template>

<script>
import {
  defineComponent,
  reactive,
  toRefs,
  computed,
  watch,
  toRaw,
  ref,
  nextTick,
} from "vue";
import request from "../../../../common/utils/request";
import store from "../../../../store/index";
import { useRoute, useRouter } from "vue-router";
import utils from "../../../../common/utils/utils";
import { Modal, notification, message } from "ant-design-vue";
import { PlusOutlined, SaveOutlined } from "@ant-design/icons-vue";
import EditItem from "./EditItem.vue";
import ChooseModule from "./ChooseModule.vue";
import draggable from "vuedraggable";

export default defineComponent({
  name: "CustomSyntheticalEdit",
  components: {
    EditItem,
    ChooseModule,
    draggable,
    PlusOutlined,
    SaveOutlined,
  },
  props: {
    village: {
      type: Object,
      default: () => {},
    },
  },

  setup(props, context) {
    const route = useRoute();
    const router = useRouter();
    const state = reactive({
      pageData: [],
      showAddModuleVisible: false,
      sideMaxSpace: 8,
      addSide: "",
      addIndex: null,
      addType: "",

      submitLoading: false,
    });

    const getSavedModules = () => {
      request
        .get("/datav", "/module/get", { village_id: props.village.id })
        .then((res) => {
          if (res.result && res.result.module_info) {
            state.pageData = res.result.module_info;
            if (state.pageData.left) {
              if (getListUsedSpace(state.pageData.left) < state.sideMaxSpace) {
                state.pageData.left.push({
                  id: -1,
                });
              }
            }
            if (state.pageData.right) {
              if (getListUsedSpace(state.pageData.right) < state.sideMaxSpace) {
                state.pageData.right.push({
                  id: -1,
                });
              }
            }
          } else {
            state.pageData = {
              left: [{ id: -1 }],
              right: [{ id: -1 }],
            };
          }
        });
    };

    const init = () => {
      getSavedModules();
    };

    init();

    const addModule = (side, index, type) => {
      state.showAddModuleVisible = true;
      state.addSide = side;
      state.addIndex = index;
      state.addType = type;
    };

    const onChooseModuleClose = (module) => {
      if (module && module.id) {
        let usedSpace = getListUsedSpace(state.pageData[state.addSide]);

        // 替换
        if (state.addType == "swap") {
          //替换组件时，被替换组件使用的空间不计算
          let current = state.pageData[state.addSide][state.addIndex];
          let currentSpace = current.columns * current.rows;
          if (
            state.sideMaxSpace - (usedSpace - currentSpace) <
            module.rows * module.columns
          ) {
            message.error("当前选用组件过大，请重新选择");
          } else {
            state.pageData[state.addSide][state.addIndex] = module;
            state.showAddModuleVisible = false;

            let l = state.pageData[state.addSide].length;
            usedSpace = getListUsedSpace(state.pageData[state.addSide]);
            if (state.sideMaxSpace - usedSpace > 0) {
              console.log("还有剩余空间", state.pageData[state.addSide][l - 1]);
              //如果有剩余空间，要补上新增按钮
              if (state.pageData[state.addSide][l - 1].id > 0) {
                state.pageData[state.addSide].push({
                  id: -1,
                });
              }
            } else {
              //无剩余空间
              console.log("无剩余空间", state.pageData[state.addSide][l - 1]);
              if (state.pageData[state.addSide][l - 1].id < 0) {
                state.pageData[state.addSide].pop();
              } else {
              }
            }
          }
        }

        // 新增
        if (state.addType == "add") {
          if (state.sideMaxSpace - usedSpace < module.rows * module.columns) {
            message.error("当前选用组件过大，请重新选择");
          } else {
            state.pageData[state.addSide][state.addIndex] = module;
            let usedSpace = getListUsedSpace(state.pageData[state.addSide]);
            //如果有剩余空间，要补上新增按钮
            if (state.sideMaxSpace - usedSpace > 0) {
              state.pageData[state.addSide].push({
                id: -1,
              });
            }
            state.showAddModuleVisible = false;
          }
        }
      } else {
        state.showAddModuleVisible = false;
      }
    };

    const onModuleDelete = (side, index) => {
      state.pageData[side].splice(index, 1);
      let l = state.pageData[side].length;
      if (state.pageData[side][l - 1].id > 0) {
        state.pageData[side].push({
          id: -1,
        });
      }
    };

    const dragOptions = computed(() => {
      return {
        animation: 200,
        group: "description",
        disabled: false,
        ghostClass: "ghost",
      };
    });

    const onMoveLeft = (e) => {
      // 如果拖拽目标是右边列表
      // 每一边最多可以放8个(2*4),
      let OverMaxCount = false;
      let targetCount = 0;
      let currentCount =
        e.draggedContext.element.columns * e.draggedContext.element.rows;
      state.pageData.right.forEach((item) => {
        targetCount += item.columns * item.rows;
      });
      if (currentCount + targetCount > state.sideMaxSpace) {
        OverMaxCount = true;
      }
      if (
        (e.relatedContext.component.targetDomElement.className ==
          "drag-list-right" &&
          OverMaxCount) ||
        e.relatedContext.element.id == -1
      ) {
        return false;
      }
      return true;
    };

    const onMoveRight = (e) => {
      // 如果拖拽目标是右边列表
      let OverMaxCount = false;
      let targetCount = 0;
      let currentCount =
        e.draggedContext.element.columns * e.draggedContext.element.rows;
      state.pageData.left.forEach((item) => {
        targetCount += item.columns * item.rows;
      });
      if (currentCount + targetCount > state.sideMaxSpace) {
        OverMaxCount = true;
      }
      if (
        (e.relatedContext.component.targetDomElement.className ==
          "drag-list-left" &&
          OverMaxCount) ||
        e.relatedContext.element.id == -1
      ) {
        return false;
      }
      return true;
    };

    // 当前组件列表已经占用的空间
    const getListUsedSpace = (list) => {
      let usedSpace = 0;
      for (let i = 0; i < list.length; i++) {
        if (list[i].id > 0) {
          // 1 x 1 组件特殊处理
          // 如果是一列的，但是下一个组件是两列，会独占一行，也按两列算
          if (list[i].columns == 1) {
            //如果已用空间是偶数，说明当前是该行的第一个
            if (usedSpace % 2 == 0) {
              // 且下一个columns == 2
              if (list[i + 1] && list[i + 1].columns == 2) {
                usedSpace += 2;
              } else {
                // 无下一个或下一个columns == 1
                usedSpace += 1;
              }
            } else {
              usedSpace += list[i].rows * list[i].columns;
            }
          } else {
            usedSpace += list[i].rows * list[i].columns;
          }
        }
      }
      return usedSpace;
    };

    const onDragUpdate = (e) => {
      // 如果拖拽完有剩余空间，则显示添加按钮
      // 如果没有剩余空间，隐藏添加按钮
      let side = e.to.className == "drag-list-left" ? "left" : "right";
      let usedSpace = getListUsedSpace(state.pageData[side]);
      let l = state.pageData[side].length;
      if (usedSpace < state.sideMaxSpace) {
        // 显示
        if (state.pageData[side][l - 1].id > 0) {
          state.pageData[side].push({
            id: -1,
          });
        }
      } else {
        // 隐藏
        if (state.pageData[side][l - 1].id < 0) {
          state.pageData[side].pop();
        }
      }
    };

    //从左边拖拽到右边
    const onLeftDragFinish = (e) => {
      // 如果拖拽完有剩余空间，则显示添加按钮
      // 如果没有剩余空间，隐藏添加按钮
      let usedSpaceL = getListUsedSpace(state.pageData.left);
      let l1 = state.pageData.left.length;
      if (usedSpaceL < state.sideMaxSpace) {
        // 显示
        if (state.pageData.left[l1 - 1].id > 0) {
          state.pageData.left.push({
            id: -1,
          });
        }
      } else {
        // 隐藏
        if (state.pageData.left[l1 - 1].id < 0) {
          state.pageData.left.pop();
        }
      }

      let usedSpaceR = getListUsedSpace(state.pageData.right);
      let l2 = state.pageData.right.length;
      if (usedSpaceR < state.sideMaxSpace) {
        // 显示
        if (state.pageData.right[l2 - 1].id > 0) {
          state.pageData.right.push({
            id: -1,
          });
        }
      } else {
        // 隐藏
        if (state.pageData.right[l2 - 1].id < 0) {
          state.pageData.right.pop();
        }
      }
    };

    //从右边拖拽到左边
    const onRightDragFinish = (e) => {
      // 如果拖拽完有剩余空间，则显示添加按钮
      // 如果没有剩余空间，隐藏添加按钮
      let usedSpaceL = getListUsedSpace(state.pageData.left);
      let l1 = state.pageData.left.length;
      if (usedSpaceL < state.sideMaxSpace) {
        // 显示
        if (state.pageData.left[l1 - 1].id > 0) {
          state.pageData.left.push({
            id: -1,
          });
        }
      } else {
        // 隐藏
        if (state.pageData.left[l1 - 1].id < 0) {
          state.pageData.left.pop();
        }
      }

      let usedSpaceR = getListUsedSpace(state.pageData.right);
      let l2 = state.pageData.right.length;
      if (usedSpaceR < state.sideMaxSpace) {
        // 显示
        if (state.pageData.right[l2 - 1].id > 0) {
          state.pageData.right.push({
            id: -1,
          });
        }
      } else {
        // 隐藏
        if (state.pageData.right[l2 - 1].id < 0) {
          state.pageData.right.pop();
        }
      }
    };

    const onSubmit = () => {
      state.submitLoading = true;
      let params = {
        village_id: props.village.id,
        module_info: {},
      };
      let data = JSON.parse(JSON.stringify(state.pageData));
      let leftList = data.left.filter((item) => item.id > 0);
      let rightList = data.right.filter((item) => item.id > 0);
      params.module_info.left = leftList;
      params.module_info.right = rightList;

      request.post("/datav", "/module/operate", { ...params }).then((res) => {
        message.success("发布成功");
        state.submitLoading = false;
      });
    };

    watch(
      () => props.village,
      (val) => {
        init();
      }
    );

    return {
      ...toRefs(state),
      addModule,
      onChooseModuleClose,
      onModuleDelete,
      dragOptions,
      onMoveLeft,
      onMoveRight,
      onDragUpdate,
      onLeftDragFinish,
      onRightDragFinish,
      onSubmit,
    };
  },
});
</script>

<style lang="less" scoped>
@import "../../styles/vars.less";
@import "../../styles/common.less";
.custom-page {
  .left {
    position: fixed;
    z-index: 30;
    left: @bodyLRPadding;
    top: @headerHeight + 1rem;
    bottom: @tabHeight;
    width: 40rem;
    pointer-events: auto;
    height: 85%;
  }

  .right {
    position: fixed;
    z-index: 30;
    right: @bodyLRPadding;
    top: @headerHeight + 1rem;
    bottom: @tabHeight;
    width: 40rem;
    pointer-events: auto;
    height: 85%;
  }

  .modules-row {
    height: 100%;

    .drag-list-left,
    .drag-list-right {
      width: 100%;
      height: 100%;
      display: flex;
      flex-wrap: wrap;
      align-content: flex-start;
    }

    .modules-col {
    }

    .empty-item-wrap {
      width: 100%;
      height: 100%;
      padding-bottom: 1rem;

      .empty-item {
        width: 100%;
        height: 100%;
        border: 1px dashed #ccc;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        color: #fff;
        border-radius: 0.4rem;
        cursor: pointer;
      }
    }
  }

  .save-button {
    position: fixed;
    z-index: 30;
    pointer-events: all;
    width: 80px;
    height: 32px;
    bottom: 6rem;
    left: 0;
    right: 0;
    margin: 0 auto;
  }
}
</style>
